﻿using CPPEI.WebApi2;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace CPPEI.WebApi
{
    static class ParameterInjection
    {
        public static void Injection4Get(HttpRequest httpRequest, object parameter)
        {
            #region property
            PropertyInfo[] propertyArr = parameter.GetType().GetProperties();
            foreach (PropertyInfo property in propertyArr)
            {
                string paramString = string.Empty;

                DefaultAttribute defaultAttribute = property.GetCustomAttribute<DefaultAttribute>();
                ParameterAttribute paramAttribute = property.GetCustomAttribute<ParameterAttribute>();
                if (paramAttribute != null)
                {
                    #region has parameter
                    if (string.IsNullOrEmpty(paramAttribute.Namespace))
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = paramAttribute.Name;
                        }
                        else
                        {
                            paramString = property.Name;
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, paramAttribute.Name);
                        }
                        else
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, property.Name);
                        }
                    }
                    #endregion
                }
                else
                {
                    paramString = property.Name;
                }

                try
                {
                    object value = GetValue4Get(property.PropertyType, httpRequest, paramString);
                    if (value == null && defaultAttribute != null)
                    {
                        value = defaultAttribute.Value;
                    }
                    property.SetValue(parameter, value, null);
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
            #endregion

            #region field
            FieldInfo[] fieldArr = parameter.GetType().GetFields();
            foreach (FieldInfo field in fieldArr)
            {
                string paramString = string.Empty;

                DefaultAttribute defaultAttribute = field.GetCustomAttribute<DefaultAttribute>();
                ParameterAttribute paramAttribute = field.GetCustomAttribute<ParameterAttribute>();
                if (paramAttribute != null)
                {
                    #region has parameter
                    if (string.IsNullOrEmpty(paramAttribute.Namespace))
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = paramAttribute.Name;
                        }
                        else
                        {
                            paramString = field.Name;
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, paramAttribute.Name);
                        }
                        else
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, field.Name);
                        }
                    }
                    #endregion
                }
                else
                {
                    paramString = field.Name;
                }

                try
                {
                    object value = GetValue4Get(field.FieldType, httpRequest, paramString);
                    if (value == null && defaultAttribute != null)
                    {
                        value = defaultAttribute.Value;
                    }
                    field.SetValue(parameter, value);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            #endregion
        }

        public static T InjectionJsonWithPost<T>(HttpRequest httpRequest)
        {
            string requestBody = null;
            using (StreamReader reader = new StreamReader(httpRequest.InputStream))
            {
                requestBody = reader.ReadToEnd();
            }
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(requestBody);
            
        }

        public static void Injection4Post(HttpRequest httpRequest, object parameter)
        {
            #region property
            PropertyInfo[] propertyArr = parameter.GetType().GetProperties();
            foreach (PropertyInfo property in propertyArr)
            {
                string paramString = string.Empty;

                DefaultAttribute defaultAttribute = property.GetCustomAttribute<DefaultAttribute>();
                ParameterAttribute paramAttribute = property.GetCustomAttribute<ParameterAttribute>();
                if (paramAttribute != null)
                {
                    if (string.IsNullOrEmpty(paramAttribute.Namespace))
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = paramAttribute.Name;
                        }
                        else
                        {
                            paramString = property.Name;
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, paramAttribute.Name);
                        }
                        else
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, property.Name);
                        }
                    }
                }
                else
                {
                    paramString = property.Name;
                }

                try
                {
                    object value = GetValue4Post(property.PropertyType, httpRequest, paramString);
                    if (value == null && defaultAttribute != null)
                    {
                        value = defaultAttribute.Value;
                    }
                    property.SetValue(parameter, value, null);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            #endregion

            #region field
            FieldInfo[] fieldArr = parameter.GetType().GetFields();
            foreach (FieldInfo field in fieldArr)
            {
                string paramString = string.Empty;

                DefaultAttribute defaultAttribute = field.GetCustomAttribute<DefaultAttribute>();
                ParameterAttribute paramAttribute = field.GetCustomAttribute<ParameterAttribute>();
                if (paramAttribute != null)
                {
                    #region has parameter
                    if (string.IsNullOrEmpty(paramAttribute.Namespace))
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = paramAttribute.Name;
                        }
                        else
                        {
                            paramString = field.Name;
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(paramAttribute.Name))
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, paramAttribute.Name);
                        }
                        else
                        {
                            paramString = string.Format("{0}:{1}", paramAttribute.Namespace, field.Name);
                        }
                    }
                    #endregion
                }
                else
                {
                    paramString = field.Name;
                }

                try
                {
                    object value = GetValue4Post(field.FieldType, httpRequest, paramString);
                    if (value == null && defaultAttribute != null)
                    {
                        value = defaultAttribute.Value;
                    }
                    field.SetValue(parameter, value);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            #endregion
        }

        private static object GetValue4Get(Type valueType, HttpRequest httpRequest, string paramString)
        {
            if (valueType == typeof(string))
            {
                return httpRequest.QueryString[paramString];
            }
            else if (valueType == typeof(int))
            {
                string strValue = httpRequest.QueryString[paramString];
                if(string.IsNullOrEmpty(strValue))
                {
                    return null;
                }
                int retValue = 0;
                if(int.TryParse(strValue, out retValue))
                {
                    return retValue;
                }
                return null;
            }
            else if (valueType == typeof(Guid))
            {
                Guid retValue = Guid.Empty;
                Guid.TryParse(httpRequest.QueryString[paramString], out retValue);
                return retValue;
            }
            else if (valueType == typeof(DateTime))
            {
                return Convert.ToDateTime(httpRequest.QueryString[paramString]);
            }
            else if (valueType == typeof(Boolean))
            {
                bool retValue = false;
                if (Boolean.TryParse(httpRequest.QueryString[paramString], out retValue))
                {
                }
                return retValue;
            }
            else if(valueType == typeof(Version))
            {
                Version retValue =null;
                if(Version.TryParse(httpRequest.QueryString[paramString], out retValue))
                {
                    return retValue;
                }
                else
                {
                    throw new Exception("参数转化失败");
                }
            }
            return httpRequest.QueryString[paramString];
        }

        private static object GetValue4Post(Type valueType, HttpRequest httpRequest, string paramString)
        {
            if (valueType == typeof(string))
            {
                return httpRequest.Form[paramString];
            }
            else if (valueType == typeof(int))
            {
                return Convert.ToInt32(httpRequest.Form[paramString]);
            }
            else if (valueType == typeof(Guid))
            {
                Guid retValue = Guid.Empty;
                Guid.TryParse(httpRequest.Form[paramString], out retValue);
                return retValue;
            }
            else if (valueType == typeof(DateTime))
            {
                return Convert.ToDateTime(httpRequest.Form[paramString]);
            }
            else if(valueType == typeof(Boolean))
            {
                bool retValue = false;
                if(Boolean.TryParse(httpRequest.Form[paramString], out retValue))
                {
                }
                return retValue;
            }
            else if (valueType == typeof(HttpPostedFile))
            {
                return httpRequest.Files[paramString];
            }
            else if (valueType == typeof(Version))
            {
                Version retValue = null;
                if (Version.TryParse(httpRequest.Form[paramString], out retValue))
                {
                    return retValue;
                }
                else
                {
                    throw new Exception("参数转化失败");
                }
            }
            else if (valueType.IsArray)
            {
                Type itemType = valueType.GetElementType();

                string[] values = httpRequest.Form.GetValues(paramString);
                return GetArray(itemType, values);
            }
            return httpRequest.Form[paramString];
        }

        private static Array GetArray(Type valueType, string[] values)
        {
            if (valueType == typeof(string))
            {
                return values;
            }
            else if (valueType == typeof(int))
            {
                int[] intValues = new int[values.Length];
                for (int index = 0; index < values.Length; index++)
                {
                    intValues[index] = Convert.ToInt32(values[index]);
                }
                return intValues;
            }
            else if (valueType == typeof(Guid))
            {
                Guid[] guidValues = new Guid[values.Length];
                for (int index = 0; index < values.Length; index++)
                {
                    guidValues[index] = new Guid(values[index]);
                }
                return guidValues;
            }
            else if (valueType == typeof(DateTime))
            {
                DateTime[] array = new DateTime[values.Length];
                for (int index = 0; index < values.Length; index++)
                {
                    array[index] = Convert.ToDateTime(values[index]);
                }
                return array;
            }
            else if(valueType == typeof(Boolean))
            {
                Boolean[] array = new Boolean[values.Length];
                for (int index = 0; index < values.Length; index++)
                {
                    array[index] = Convert.ToBoolean(values[index]);
                }
                return array;
            }
            else if (valueType == typeof(Version))
            {
                Version[] array = new Version[values.Length];
                for (int index = 0; index < values.Length; index++)
                {
                    array[index] = new Version(values[index]);
                }
                return array;
            }
            return null;
        }
    }
}
